package com.duoec.magichour.service.impl;

import com.duoec.magichour.core.exceptions.BusinessException;
import com.duoec.magichour.dto.ArticleCateTreeNode;
import com.duoec.magichour.dto.BaseResponse;
import com.duoec.magichour.dto.UserInfo;
import com.duoec.magichour.dto.request.ArticleCateSave;
import com.duoec.magichour.mapper.ArticleCateMapper;
import com.duoec.magichour.pojo.ArticleCate;
import com.duoec.magichour.service.ArticleCateService;
import com.duoec.magichour.service.ArticleService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * Created by ycoe on 17/6/30.
 */
@Service
public class ArticleCateServiceImpl implements ArticleCateService {
    @Autowired
    private ArticleCateMapper articleCateMapper;

    @Autowired
    private ArticleService articleService;

    private List<ArticleCateTreeNode> roots;

    private Map<Integer, ArticleCateTreeNode> articleCateTreeMap;

    @Override
    public Integer save(UserInfo userInfo, ArticleCateSave request) {
        ArticleCate ac = new ArticleCate();
        ac.setName(request.getName());
        ac.setParentId(request.getParentId());
        if (request.getId() != null && request.getId() > 0) {
            //修改
            ac.setId(request.getId());
            articleCateMapper.updateByPrimaryKeySelective(ac);
        } else {
            //新增
            articleCateMapper.insertSelective(ac);
        }
        //重新构建树
        initRoots();
        return ac.getId();
    }

    @Override
    public void availableParentId(Integer id, Integer parentId) throws BusinessException {
        if (parentId == null || parentId.equals(0)) {
            return;
        }
        if (!exists(parentId)) {
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "父级分类不存在！");
        }
        if (id == null) {
            return;
        }

        //父级ID不允许是当前ID或子类
        if (id.equals(parentId)) {
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "父级分类不能是自己或子分类！");
        }
        ArticleCateTreeNode currentNode = articleCateTreeMap.get(id);
        //不能是自己的子类
        List<ArticleCateTreeNode> children = currentNode.getChildren();
        if (children != null) {
            children.forEach(child -> availableParentId(child.getId(), parentId));
        }
    }

    @Override
    public boolean exists(Integer id) {
        return articleCateTreeMap.containsKey(id);
    }

    @Transactional
    @Override
    public void delete(int id) {
        articleCateMapper.delete(id);

        // 将此文章的分类设置为0（未分类）
        articleService.changeArticleCate(id, 0);

        //重新加载文章分类
        initRoots();
    }

    @Override
    public String getName(Integer cateId) {
        ArticleCateTreeNode node = articleCateTreeMap.get(cateId);
        return node == null ? "未分类" : node.getName();
    }

    /**
     * 初始化树
     */
    @PostConstruct
    public void initRoots() {
        roots = Lists.newArrayList();
        List<ArticleCate> articleCateList = articleCateMapper.findAll();
        articleCateTreeMap = Maps.newHashMap();
        if (articleCateList == null) {
            return;
        }
        articleCateList.forEach(articleCate -> {
            ArticleCateTreeNode node = new ArticleCateTreeNode();
            BeanUtils.copyProperties(articleCate, node);

            articleCateTreeMap.put(articleCate.getId(), node);
            Integer parentId = articleCate.getParentId();
            if (parentId == null || parentId.equals(0)) {
                //根
                roots.add(node);
                return;
            }
            ArticleCateTreeNode parent = articleCateTreeMap.get(parentId);
            if (parent == null) {
                return;
            }

            List<ArticleCateTreeNode> children = parent.getChildren();
            if (children == null) {
                children = Lists.newArrayList();
                parent.setChildren(children);
            }
            children.add(node);
            node.setParent(parent);
        });
        return;
    }
}
